﻿#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    BaseEditor(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // setWindowFlag(Qt::WindowStaysOnTopHint);

    table=P_LAUNCHER;
    isConfigChanged=false;

    //接受拖放
    ui->appWidget->setAcceptDrops(true);
    ui->locationWidget->setAcceptDrops(true);
    ui->fileWidget->setAcceptDrops(true);

    //图标模式
    ui->appWidget->setViewMode(QListWidget::IconMode);
    ui->locationWidget->setViewMode(QListWidget::IconMode);
    ui->fileWidget->setViewMode(QListWidget::IconMode);

    //换行显示
    ui->appWidget->setLayoutMode(QListWidget::Batched);
    ui->locationWidget->setLayoutMode(QListWidget::Batched);
    ui->fileWidget->setLayoutMode(QListWidget::Batched);

    //尺寸变化时自动调整尺寸
    ui->appWidget->setResizeMode(QListWidget::Adjust);
    ui->locationWidget->setResizeMode(QListWidget::Adjust);
    ui->fileWidget->setResizeMode(QListWidget::Adjust);

    updateView();
    createTray();
    createMenu();
    loadLocation();
    startTimer(AUTOSAVE_INTERVAL);

    invoker.fetchData(table,MT_LINK);
}

Widget::~Widget()
{
    saveLocation();
    delete ui;
}

void Widget::updateView()
{
    updateAppView();
    updateLocationView();
    updateFileView();
}

void Widget::createMenu()
{
    menu=new QMenu(this);
}

void Widget::updateMenu()
{
    if(!menu->isEmpty())
        menu->clear();

    QMenu *viewMenu=menu->addMenu(QStringLiteral("查看"));
    viewMenu->addAction(QStringLiteral("小图标"),this,&Widget::do_setIconSizeS);
    viewMenu->addAction(QStringLiteral("中图标"),this,&Widget::do_setIconSizeM);
    viewMenu->addAction(QStringLiteral("大图标"),this,&Widget::do_setIconSizeL);
    viewMenu->addSeparator();
    viewMenu->addAction(QStringLiteral("更新视图 (F5)"),this,&Widget::do_updateView);
    menu->addSeparator();
    menu->addAction(QStringLiteral("添加 (F1)"),this,&Widget::do_addItem);
    menu->addSeparator();
    QMenu *optionMenu=menu->addMenu(QStringLiteral("选项"));
    optionMenu->addAction(QStringLiteral("重命名 (F2)"),this,&Widget::do_setItemLabel);
    optionMenu->addAction(QStringLiteral("设置图标 (F3)"),this,&Widget::do_setItemIcon);
    optionMenu->addSeparator();
    optionMenu->addAction(QStringLiteral("打开位置 (F4)"),this,&Widget::do_openItemLocation);
    optionMenu->addSeparator();
    optionMenu->addAction(QStringLiteral("删除 (Delete)"),this,&Widget::do_removeItem);
    if(ui->toolBox->currentIndex() == IDX_LOCATION)
    {
        optionMenu->addSeparator();
        optionMenu->addAction(QStringLiteral("添加常用位置"),this,&Widget::do_addStandardPaths);
    }
}

void Widget::contextMenuEvent(QContextMenuEvent *)
{
    updateMenu();
    menu->exec(QCursor::pos());
}

void Widget::do_updateView()
{
    updateView(ui->toolBox->currentIndex());
}

void Widget::dragEnterEvent(QDragEnterEvent *event)
{
    //如果为文件，则支持拖放
    if(event->mimeData()->hasUrls())
        event->acceptProposedAction();
}

void Widget::dropEvent(QDropEvent *event)
{
    QList<QUrl> urls = event->mimeData()->urls();
    if(urls.isEmpty())
        return;

    QString category,label,detail;
    detail=urls.first().toLocalFile();
    detail=QFileInfo(detail).isSymLink() ?
                QFileInfo(detail).symLinkTarget() : detail;

    int idx=ui->toolBox->currentIndex();
    switch (idx) {
    case IDX_APP:
    {
        category=MT_PROGRAM;
        QFileInfo fileInfo(detail);
        if(fileInfo.isFile() && fileInfo.isExecutable())
        {
            label=fileInfo.baseName();
            if(appItems.keys().contains(label))
                return;
        }
    }
        break;
    case IDX_LOCATION:
    {
        category=MT_LOCATION;
        QFileInfo fileInfo(detail);
        if(fileInfo.isDir())
        {
            label=fileInfo.baseName();
            if(locationItems.keys().contains(label))
                return;
        }
    }
        break;
    case IDX_FILE:
    {
        category=MT_FILE;
        QFileInfo fileInfo(detail);
        if(fileInfo.isFile())
        {
            label=fileInfo.baseName();
            if(fileItems.keys().contains(label))
                return;
        }
    }
        break;
    }

    if(category.isEmpty() || label.isEmpty() || detail.isEmpty())
        return;

    if(sp_addItemByCategory(table,category,label,detail,QString()))
        updateView(idx);
    else
        QMessageBox::warning(this,QStringLiteral("异常情况"),
                             QStringLiteral("提交失败！"));
}

void Widget::loadLocation()
{
    if(QFile::exists(configFile))
    {
        QSettings cfg(configFile,QSettings::IniFormat);
        int x=cfg.value("Location/x").toInt();
        int y=cfg.value("Location/y").toInt();
        x=(x>0 ? x : 200);
        y=(y>0 ? y : 100);
        move(x,y);

        int pageIndex=cfg.value("Main/lastPage").toInt();
        pageIndex=(pageIndex >= 0 ? pageIndex : 0);
        ui->toolBox->setCurrentIndex(pageIndex);

        int appSize=cfg.value("Main/lastAppSize").toInt();
        appSize=(appSize >= 0 ? appSize : 0);
        setAppIconSize(appSize);

        int folderSize=cfg.value("Main/lastFolderSize").toInt();
        folderSize=(folderSize >= 0 ? folderSize : 0);
        setLocationIconSize(folderSize);

        int fileSize=cfg.value("Main/lastFileSize").toInt();
        fileSize=(fileSize >= 0 ? fileSize : 0);
        setFileIconSize(fileSize);
    }
}

void Widget::saveLocation()
{
    QSettings cfg(configFile,QSettings::IniFormat);
    cfg.setValue("Location/x",x());
    cfg.setValue("Location/y",y());
    cfg.setValue("Main/lastPage",ui->toolBox->currentIndex());
    cfg.setValue("Main/lastAppSize",appSizeIndicator);
    cfg.setValue("Main/lastFolderSize",locationSizeIndicator);
    cfg.setValue("Main/lastFileSize",fileSizeIndicator);
}

void Widget::setAppIconSize(int index)
{
    appSizeIndicator=index;
    switch (index) {
    case IDX_SIZE_S:
        ui->appWidget->setIconSize(SIZE_S);
        break;
    case IDX_SIZE_M:
        ui->appWidget->setIconSize(SIZE_M);
        break;
    case IDX_SIZE_L:
        ui->appWidget->setIconSize(SIZE_L);
        break;
    }

    if(!isConfigChanged)
        isConfigChanged=true;
}

void Widget::setLocationIconSize(int index)
{
    locationSizeIndicator=index;
    switch (index) {
    case IDX_SIZE_S:
        ui->locationWidget->setIconSize(SIZE_S);
        break;
    case IDX_SIZE_M:
        ui->locationWidget->setIconSize(SIZE_M);
        break;
    case IDX_SIZE_L:
        ui->locationWidget->setIconSize(SIZE_L);
        break;
    }

    if(!isConfigChanged)
        isConfigChanged=true;
}

void Widget::setFileIconSize(int index)
{
    fileSizeIndicator=index;
    switch (index) {
    case IDX_SIZE_S:
        ui->fileWidget->setIconSize(SIZE_S);
        break;
    case IDX_SIZE_M:
        ui->fileWidget->setIconSize(SIZE_M);
        break;
    case IDX_SIZE_L:
        ui->fileWidget->setIconSize(SIZE_L);
        break;
    }

    if(!isConfigChanged)
        isConfigChanged=true;
}

void Widget::updateView(int index)
{
    switch (index) {
    case IDX_APP:
        updateAppView();
        break;
    case IDX_LOCATION:
        updateLocationView();
        break;
    case IDX_FILE:
        updateFileView();
        break;
    }
}

void Widget::updateAppView()
{
    if(!appItems.isEmpty())
        appItems.clear();

    if(ui->appWidget->count() != 0)
        ui->appWidget->clear();

    QSqlQuery query;
    query.exec(QString("select label,detail,addition from %1 where category='%2'")
               .arg(table)
               .arg(MT_PROGRAM));

    while (query.next()) {
        QString label=query.value("label").toString();
        QString detail=query.value("detail").toString();
        if(label.isEmpty() || detail.isEmpty())
            continue;

        QString addition=query.value("addition").toString();
        appItems.insert(label,detail);

        QListWidgetItem *item = new QListWidgetItem(label);
        QString iconFile=DEF_APP_ICON;
        if(!addition.isEmpty())
            iconFile=addition;
        item->setIcon(QIcon(iconFile));
        ui->appWidget->addItem(item);
    }
    if(ui->appWidget->count() > 1)
        ui->appWidget->sortItems();
}

void Widget::updateFileView()
{
    if(!fileItems.isEmpty())
        fileItems.clear();

    if(ui->fileWidget->count() != 0)
        ui->fileWidget->clear();

    QSqlQuery query;
    query.exec(QString("select label,detail,addition from %1 where category='%2'")
               .arg(table)
               .arg(MT_FILE));

    while (query.next()) {
        QString label=query.value("label").toString();
        QString detail=query.value("detail").toString();
        if(label.isEmpty() || detail.isEmpty())
            continue;

        QString addition=query.value("addition").toString();
        fileItems.insert(label,detail);

        QListWidgetItem *item = new QListWidgetItem(label);
        QString iconFile=DEF_FILE_ICON;
        if(!addition.isEmpty())
            iconFile=addition;
        item->setIcon(QIcon(iconFile));
        ui->fileWidget->addItem(item);
    }

    if(ui->fileWidget->count() > 1)
        ui->fileWidget->sortItems();
}

void Widget::updateLocationView()
{
    if(!locationItems.isEmpty())
        locationItems.clear();

    if(ui->locationWidget->count() != 0)
        ui->locationWidget->clear();

    QSqlQuery query;
    query.exec(QString("select label,detail,addition from %1 where category='%2'")
               .arg(table)
               .arg(MT_LOCATION));

    while (query.next()) {
        QString label=query.value("label").toString();
        QString detail=query.value("detail").toString();
        if(label.isEmpty() || detail.isEmpty())
            continue;

        QString addition=query.value("addition").toString();
        locationItems.insert(label,detail);

        QListWidgetItem *item = new QListWidgetItem(label);
        if(addition.isEmpty())
        {
            addition=sp_getFolderIconPath(detail);
            sp_updateColumnByCategory(table,"addition",addition,MT_LOCATION,label);
        }

        item->setIcon(QIcon(addition));
        ui->locationWidget->addItem(item);
    }

    if(ui->locationWidget->count() > 1)
        ui->locationWidget->sortItems();
}

void Widget::do_addItem()
{
    QString category,label,detail;
    int idx=ui->toolBox->currentIndex();
    switch (idx) {
    case IDX_APP:
    {
        category=MT_PROGRAM;
        detail=QFileDialog::getOpenFileName(this,
                                            QStringLiteral("选择一个可执行文件"));
        if(detail.isEmpty())
            return;

        label=QFileInfo(detail).baseName();
        if(appItems.keys().contains(label))
            return;
    }
        break;
    case IDX_LOCATION:
    {
        category=MT_LOCATION;
        detail=QFileDialog::getExistingDirectory(this,
                                                 QStringLiteral("选择一个文件夹"));
        if(detail.isEmpty())
            return;

        label=QFileInfo(detail).baseName();
        if(locationItems.keys().contains(label))
            return;
    }
        break;
    case IDX_FILE:
    {
        category=MT_FILE;
        detail=QFileDialog::getOpenFileName(this,
                                            QStringLiteral("选择文件夹"));
        if(detail.isEmpty())
            return;
        label=QFileInfo(detail).fileName();
        if(fileItems.keys().contains(label))
            return;
    }
        break;
    }

    if(sp_addItemByCategory(table,category,label,detail,QString()))
        updateView(idx);
    else
        MESSAGE_CANNOT_SUBMIT
}

void Widget::do_setItemIcon()
{
    QString category,label;
    int idx=ui->toolBox->currentIndex();
    switch (idx) {
    case IDX_APP:
    {
        category=MT_PROGRAM;
        if(ui->appWidget->count() < 1)
            return;
        label=ui->appWidget->currentItem()->text();
    }
        break;
    case IDX_LOCATION:
    {
        category=MT_LOCATION;
        if(ui->locationWidget->count() < 1)
            return;
        label=ui->locationWidget->currentItem()->text();
    }
        break;
    case IDX_FILE:
    {
        category=MT_FILE;
        if(ui->fileWidget->count() < 1)
            return;
        label=ui->fileWidget->currentItem()->text();
    }
        break;
    }

    if(category.isEmpty() || label.isEmpty())
        return;

    QString addition=QFileDialog::getOpenFileName(this,
                                                  QStringLiteral("选择一个图标文件"),
                                                  QString(),
                                                  QStringLiteral("图标文件 (*.png *.ico *.svg)"));
    if(addition.isEmpty())
        return;

    if(sp_updateColumnByCategory(table,"addition",addition,category,label))
        updateView(idx);
}

void Widget::do_openItemLocation()
{
    QString label,detail;
    switch (ui->toolBox->currentIndex()) {
    case IDX_APP:
    {
        if(ui->appWidget->count() < 1)
            return;
        label=ui->appWidget->currentItem()->text();
        detail=appItems.value(label);
    }
        break;
    case IDX_LOCATION:
    {
        if(ui->locationWidget->count() < 1)
            return;
        label=ui->locationWidget->currentItem()->text();
        detail=locationItems.value(label);
    }
        break;
    case IDX_FILE:
    {
        if(ui->fileWidget->count() < 1)
            return;
        label=ui->fileWidget->currentItem()->text();
        detail=fileItems.value(label);
    }
        break;
    }

    if(detail.isEmpty())
        return;

    QString path=QFileInfo(detail).path();
    if(QFileInfo::exists(path))
        QDesktopServices::openUrl(QUrl::fromLocalFile(path));
}

void Widget::do_setItemLabel()
{
    QString category,label;
    int idx=ui->toolBox->currentIndex();
    switch (idx) {
    case IDX_APP:
    {
        if(ui->appWidget->count() < 1)
            return;
        category=MT_PROGRAM;
        label=ui->appWidget->currentItem()->text();
    }
        break;
    case IDX_LOCATION:
    {
        if(ui->locationWidget->count() < 0)
            return;
        category=MT_LOCATION;
        label=ui->locationWidget->currentItem()->text();
    }
        break;
    case IDX_FILE:
    {
        if(ui->fileWidget->count() < 0)
            return;
        category=MT_FILE;
        label=ui->fileWidget->currentItem()->text();
    }
        break;
    }

    if(category.isEmpty() || label.isEmpty())
        return;

    QString newLabel=QInputDialog::getText(this,QStringLiteral("输入新标签"),
                                           QStringLiteral("标签："),
                                           QLineEdit::Normal,
                                           label);

    if(newLabel.isEmpty() || newLabel == label)
        return;

    if(sp_updateColumnByCategory(table,"label",newLabel,category,label))
        updateView(idx);

    if(!isConfigChanged)
        isConfigChanged=true;
}

void Widget::do_removeItem()
{
    QString category,label;
    int idx=ui->toolBox->currentIndex();
    switch (idx) {
    case IDX_APP:
    {
        if(ui->appWidget->count() < 1)
            return;
        category=MT_PROGRAM;
        label=ui->appWidget->currentItem()->text();
    }
        break;
    case IDX_LOCATION:
    {
        if(ui->locationWidget->count() < 0)
            return;
        category=MT_LOCATION;
        label=ui->locationWidget->currentItem()->text();
    }
        break;
    case IDX_FILE:
    {
        if(ui->fileWidget->count() < 0)
            return;
        category=MT_FILE;
        label=ui->fileWidget->currentItem()->text();
    }
        break;
    }

    if(category.isEmpty() || label.isEmpty())
        return;

    QMessageBox::StandardButton result=MESSAGE_DELETE_CONFIRM
            if(result == QMessageBox::Yes)
    {
            if(sp_removeItemByCategory(table,category,label))
            updateView(idx);
}
}

void Widget::createTray()
{
    trayMenu=new QMenu(this);
    trayMenu->addAction(QStringLiteral("退出"),QApplication::quit);

    tray=new QSystemTrayIcon(this);
    tray->setIcon(QIcon(":/launcher.ico"));
    tray->setContextMenu(trayMenu);
    tray->setToolTip(QString(SP_NAME) + QString(" ") + SP_VERSION);
    connect(tray,&QSystemTrayIcon::activated,this,&Widget::trayActivated);
    tray->show();
}

void Widget::trayActivated(QSystemTrayIcon::ActivationReason reason)
{
    if(reason == QSystemTrayIcon::DoubleClick)
    {
        if(isVisible())
            hide();
        else
            show();
    }
}

void Widget::do_setIconSizeS()
{
    switch (ui->toolBox->currentIndex()) {
    case IDX_APP:
        setAppIconSize(IDX_SIZE_S);
        break;
    case IDX_LOCATION:
        setLocationIconSize(IDX_SIZE_S);
        break;
    case IDX_FILE:
        setFileIconSize(IDX_SIZE_S);
        break;
    }

    if(!isConfigChanged)
        isConfigChanged=true;
}

void Widget::do_setIconSizeM()
{
    switch (ui->toolBox->currentIndex()) {
    case IDX_APP:
        setAppIconSize(IDX_SIZE_M);
        break;
    case IDX_LOCATION:
        setLocationIconSize(IDX_SIZE_M);
        break;
    case IDX_FILE:
        setFileIconSize(IDX_SIZE_M);
        break;
    }

    if(!isConfigChanged)
        isConfigChanged=true;
}

void Widget::do_setIconSizeL()
{
    switch (ui->toolBox->currentIndex()) {
    case IDX_APP:
        setAppIconSize(IDX_SIZE_L);
        break;
    case IDX_LOCATION:
        setLocationIconSize(IDX_SIZE_L);
        break;
    case IDX_FILE:
        setFileIconSize(IDX_SIZE_L);
        break;
    }

    if(!isConfigChanged)
        isConfigChanged=true;
}

void Widget::on_appWidget_itemDoubleClicked(QListWidgetItem *item)
{
    QString detail=appItems.value(item->text());
    if(QFileInfo::exists(detail))
        QDesktopServices::openUrl(QUrl::fromLocalFile(detail));
}

void Widget::on_fileWidget_itemDoubleClicked(QListWidgetItem *item)
{
    QString detail=fileItems.value(item->text());
    if(QFileInfo::exists(detail))
        QDesktopServices::openUrl(QUrl::fromLocalFile(detail));
}

void Widget::on_locationWidget_itemDoubleClicked(QListWidgetItem *item)
{
    QString detail=locationItems.value(item->text());
    if(QFileInfo::exists(detail))
        QDesktopServices::openUrl(QUrl::fromLocalFile(detail));
}

void Widget::addStandardPath(const QString &path)
{
    QString label=QFileInfo(path).baseName();
    if(!locationItems.keys().contains(label))
        sp_addItemByCategory(table,MT_LOCATION,label,path,QString());
}

void Widget::do_addStandardPaths()
{
    addStandardPath(Location::home);
    addStandardPath(Location::music);
    addStandardPath(Location::video);
    addStandardPath(Location::picture);
    addStandardPath(Location::desktop);
    addStandardPath(Location::document);
    addStandardPath(Location::download);
    addStandardPath(Location::fontLocation);
    updateLocationView();
}

void Widget::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
    case Qt::Key_F1:
        do_addItem();
        break;
    case Qt::Key_F2:
        do_setItemLabel();
        break;
    case Qt::Key_F3:
        do_setItemIcon();
        break;
    case Qt::Key_F4:
        do_openItemLocation();
        break;
    case Qt::Key_F5:
        do_updateView();
        break;
    case Qt::Key_Delete:
        do_removeItem();
        break;
    case Qt::Key_Escape:
        close();
        break;
    }
}

void Widget::do_autoSaveLocation()
{
    if(!isConfigChanged)
        return;

    QSettings cfg(configFile,QSettings::IniFormat);
    cfg.setValue("Location/x",x());
    cfg.setValue("Location/y",y());
    cfg.setValue("Main/lastPage",ui->toolBox->currentIndex());
    cfg.setValue("Main/lastAppSize",appSizeIndicator);
    cfg.setValue("Main/lastFolderSize",locationSizeIndicator);
    cfg.setValue("Main/lastFileSize",fileSizeIndicator);

    isConfigChanged=false;
}

void Widget::timerEvent(QTimerEvent *)
{
    do_autoSaveLocation();
}

void Widget::on_kw_returnPressed()
{
    QString kw=ui->kw->text().trimmed();
    if(kw.isEmpty())
        return;

    invoker.invoke(kw);
    ui->kw->clear();
}
